#include <iostream>
#include <memory>
#include <string>
#include <functional>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <vector>
#include <semaphore.h>

#include "PackageParse.hpp"
#include "Reactor.hpp"
#include "Connection.hpp"
#include "Listener.hpp"
#include "HandlerConnection.hpp"

using namespace socket_ns;
static const int gforksize = 5;

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        std::cout << "Usage:\n\t" << argv[0] << " port" << std::endl;
        return 0;
    }

    uint16_t serverport = std::stoi(argv[1]);

    int pipefd[2];
    int n = pipe(pipefd);
    if (n < 0)
    {
        LOG(FATAL, "Create childpro fail");
        return -1;
    }
    HandlerConnection hc(PackageParse::Parse);
    Listener listen(serverport, hc, pipefd[1], pipefd[0]);
    sem_t sem;
    sem_init(&sem,1,1);
    std::vector<pid_t> procecess;
    pid_t pid = fork();
    if (pid != 0)
    {
        // 关闭读端
        close(pipefd[0]);
        std::unique_ptr<Reactor> r = std::make_unique<Reactor>("main", nullptr);
        r->AddConnection(listen.SockFd(), EPOLLIN | EPOLLET, std::bind(&Listener::WakeProccess, &listen, std::placeholders::_1), nullptr, nullptr);
        r->Dispatcher();
    }
    else
    {
        for (int i = 0; i < gforksize; ++i)
        {
            pid_t pid = fork();
            if (pid == 0)
            {
                std::string name = std::to_string(i);
                close(pipefd[1]);
                std::unique_ptr<Reactor> r = std::make_unique<Reactor>(name, &sem);
                r->AddConnection(pipefd[0], EPOLLIN | EPOLLET, std::bind(&Listener::Accpet, &listen, std::placeholders::_1), nullptr, nullptr);
                r->Dispatcher();
                exit(0);
            }
        }
        setsid();
        exit(0);
    }
    return 0;
}
